package com.minelx.woods.server.common;

import java.lang.annotation.Annotation;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.stream.IntStream;

import static java.util.stream.IntStream.range;

public class Parameters {
	private final Parameter[] types;

	private final Object[] values;

	public Parameters(Parameter[] types, Object[] values) {
		if (types.length != values.length) {
			throw new IllegalArgumentException("types length is not the same with values length.");
		}
		this.types = types;
		this.values = values;
	}

	public IAt<Object> type(Class<?> type) {
		return filter(parameter -> parameter.getType().equals(type));
	}

	public IAt<Object> annotatedBy(Class<? extends Annotation> annotationClass) {
		return filter(parameter -> parameter.isAnnotationPresent(annotationClass));
	}

	private IAt<Object> filter(Predicate<Parameter> what) {
		return new IndexesStreamAt<>(
				values,
				range(0, types.length).filter(index -> what.test(types[index]))
		);
	}

	public Object[] values() {
		return values;
	}

	@Override
	public String toString() {
		return "Parameters{" +
				"types=" + Arrays.toString(types) +
				", values=" + Arrays.toString(values) +
				'}';
	}

	public static Parameters empty() {
		return new Parameters(new Parameter[0], new Object[0]);
	}

}
